package device;

import memory.Memory;
import process.PCB;

import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import process.ProcessDispatcher;

import javax.swing.*;
import CPU.CPU;
//设备分配器
public class DeviceDispatcher {
    private static int size = 8;
//    设备list
    public static ObservableList<Device> deviceList;
    private static Timer[] equipTime = new Timer[size];
    private static Timer[] clockTime = new Timer[size];
//    设备分配器
    private volatile static DeviceDispatcher deviceDispatcher;

    static {
//        每个设备都有两台
        deviceList = FXCollections.observableArrayList();
        deviceList.add(new Device('A'));
        deviceList.add(new Device('A'));
        deviceList.add(new Device('B'));
        deviceList.add(new Device('B'));
        deviceList.add(new Device('B'));
        deviceList.add(new Device('C'));
        deviceList.add(new Device('C'));
        deviceList.add(new Device('C'));
        ProcessDispatcher.setDeviceList(deviceList);
    }

    public static synchronized DeviceDispatcher getInstance() {
        if (deviceDispatcher == null) {
            synchronized (DeviceDispatcher.class) {
                if (deviceDispatcher == null) {
                    deviceDispatcher = new DeviceDispatcher();
                }
            }

        }
        return deviceDispatcher;
    }

    //    检查设备
    public static boolean checkEquipment(char name) {
        System.out.println("检查能否占用设备" + name);
//        每个设备都有两台
        if (name == 'A' || name == 'a') {
            //System.out.println("检查A设备");
//            如果有A设备没被占用
            if (!deviceList.get(0).isOccupied() || !deviceList.get(1).isOccupied()) {
                System.out.println("可以占用A设备");
                return true;
            }
//            如果有B设备没被占用
        } else if (name == 'B' || name == 'b') {
            if (!deviceList.get(2).isOccupied() || !deviceList.get(3).isOccupied() || !deviceList.get(4).isOccupied()) {
                System.out.println("可以占用B设备");
                return true;
            }
//            如果有C设备没被占用
        } else if (name == 'C' || name == 'c') {
            if (!deviceList.get(5).isOccupied() || !deviceList.get(6).isOccupied() || !deviceList.get(7).isOccupied()) {
                System.out.println("可以占用C设备");
                return true;
            }

        }
        return false;
    }

    //    请求设备
    public static void requestDevice(PCB pcb, char needDevice, int holdTime) {
//        创建一个线程
        Thread thread = new Thread() {
            public void run() {
//                如果设备名字是A
                if (needDevice == 'A' || needDevice == 'a') {
//                    看设备该设备是否被占用
//                    如果一号设备没被占用
                    if (!deviceList.get(0).isOccupied()) {
//                        传入线程名，时间片，占用这个设备
                        deviceList.get(0).requestDevice(pcb.getName(), holdTime);
//                        设置计时
                        setTimerState(holdTime, 0, pcb);
                        return;
                    } else if (!deviceList.get(1).isOccupied()) {
//                    如果二号设备没被占用
                        deviceList.get(1).requestDevice(pcb.getName(), holdTime);
                        setTimerState(holdTime, 1, pcb);
                        return;
                    } else {
//                        都被占用了，直接返回
                        return;
                    }

                } else if (needDevice == 'B' || needDevice == 'b') {
                    if (!deviceList.get(2).isOccupied()) {
                        deviceList.get(2).requestDevice(pcb.getName(), holdTime);
                        setTimerState(holdTime, 2, pcb);
                        return;
                    } else if (!deviceList.get(3).isOccupied()) {
                        deviceList.get(3).requestDevice(pcb.getName(), holdTime);
                        setTimerState(holdTime, 3, pcb);
                        return;
                    } else if (!deviceList.get(4).isOccupied()) {
                        deviceList.get(4).requestDevice(pcb.getName(), holdTime);
                        setTimerState(holdTime, 4, pcb);
                        return;
                    } else {
                        return;
                    }
                } else if (needDevice == 'C' || needDevice == 'c') {
                    if (!deviceList.get(5).isOccupied()) {
                        deviceList.get(5).requestDevice(pcb.getName(), holdTime);
                        setTimerState(holdTime, 5, pcb);
                        return;
                    } else if (!deviceList.get(6).isOccupied()) {
                        deviceList.get(6).requestDevice(pcb.getName(), holdTime);
                        setTimerState(holdTime, 6, pcb);
                        return;
                    } else if (!deviceList.get(7).isOccupied()) {
                        deviceList.get(7).requestDevice(pcb.getName(), holdTime);
                        setTimerState(holdTime, 7, pcb);
                        return;
                    } else {
                        return;
                    }
                } else
                    return;

            }
        };
//        设置守护线程
        thread.setDaemon(true);
//        启动线程
        thread.start();
    }

    public static void setTimerState(int holdTime, int index, PCB pcb) {
////        当前号设备创建一个定时器
//        equipTime[index] = new Timer(1000 * (holdTime + 1), e -> {//延时holdTime秒执行
////            延时完，设置PCB到就绪进程
//            System.out.println("进程" + pcb.getName() + "占用设备" + index + "结束了！！进入就绪态");
////            设置内存中对应的线程PCB为无中断,也就是就绪
//            Memory.setPCBToReady(deviceList.get(index).getProcess());
////            对当前设备状态进行设置，设置成无占用
//            deviceList.get(index).setOccupied(false);
//            deviceList.get(index).setProcess("");
////            前端展示
//            ProcessDispatcher.showresources();
////            中断唤醒CPU
//            src.CPU.WakedUP = true;
//            System.out.println("唤醒CPU！！");
//            //System.out.println("pcb时间"+pcb.getHoldTime());
////            停止这个设备，停止 Timer，使它停止向其监听器发送动作事件
//            equipTime[index].stop();
//        });

//        一秒后更新一次PCB的设备占用时间，启动定时任务
        clockTime[index] = new Timer(1000, e -> {
//            更新进程占用设备时间-1
            pcb.setHoldTime(pcb.getHoldTime() - 1);
//            更新设备被占用的时间
            deviceList.get(index).setOccupiedTime(pcb.getHoldTime());
            System.out.println("更新线程" + pcb.getName() + "占用设备还有" + pcb.getHoldTime() + "秒");
            //            停止这个设备阻塞，停止 Timer，使它停止向其监听器发送动作事件
            if(pcb.getHoldTime()==0){
                System.out.println("唤醒CPU！！");
                //            设置内存中对应的线程PCB为无中断,也就是就绪
                Memory.setPCBToReady(deviceList.get(index).getProcess());
//            对当前设备状态进行设置，设置成无占用
                deviceList.get(index).setOccupied(false);
                deviceList.get(index).setProcess("");
//            前端展示
                ProcessDispatcher.showresources();
//            中断唤醒CPU
                CPU.WakedUP = true;
                clockTime[index].stop();
            }
        });
//        启动两个定时器
//        equipTime[index].start();
        clockTime[index].start();

    }

    public static int getFreeDeviceNum() {
        int num = 8;
        for (Device device : deviceList) {
            if (device.isOccupied()) {
                num--;
            }
        }
        return num;
    }

    public static ObservableList<Device> getDeviceList() {
        return deviceList;
    }

}
